# backend/utils/text_retriever.py
import re
from typing import List, Dict, Optional
from difflib import SequenceMatcher


class TextRetriever:
    """
    文本检索工具类，提供多种检索方法
    """
    
    def __init__(self):
        """
        初始化检索器
        """
        pass
    
    def simple_search(self, keyword: str, sentences: List[Dict], 
                     search_fields: List[str] = ['text1', 'text2'],
                     threshold: float = 0.1) -> List[Dict]:
        """
        简单关键词搜索
        
        Args:
            keyword: 搜索关键词
            sentences: 句子对列表
            search_fields: 搜索的字段名列表
            threshold: 相似度阈值
            
        Returns:
            匹配的句子对列表，每个元素包含原始数据和匹配分数
        """
        results = []
        
        # 预处理关键词
        keyword = keyword.strip().lower()
        
        if not keyword:
            return []
        
        for sentence in sentences:
            max_score = 0.0
            matched_field = None
            
            # 在指定字段中搜索
            for field in search_fields:
                if field in sentence and sentence[field]:
                    field_text = str(sentence[field]).lower()
                    
                    # 精确匹配（关键词完全出现在文本中）
                    if keyword in field_text:
                        # 计算匹配分数
                        score = self._calculate_match_score(keyword, field_text)
                        if score > max_score:
                            max_score = score
                            matched_field = field
            
            # 如果找到匹配且分数超过阈值
            if max_score >= threshold:
                result = sentence.copy()
                result['score'] = max_score
                result['matched_field'] = matched_field
                results.append(result)
        
        # 按分数降序排序
        results.sort(key=lambda x: x['score'], reverse=True)
        
        return results
    
    def advanced_search(self, keyword: str, sentences: List[Dict],
                        search_fields: List[str] = ['text1', 'text2'],
                        threshold: float = 0.3) -> List[Dict]:
        """
        高级搜索，使用相似度匹配
        
        Args:
            keyword: 搜索关键词
            sentences: 句子对列表
            search_fields: 搜索的字段名列表
            threshold: 相似度阈值
            
        Returns:
            匹配的句子对列表，每个元素包含原始数据和相似度分数
        """
        results = []
        
        # 预处理关键词
        keyword = keyword.strip().lower()
        
        if not keyword:
            return []
        
        for sentence in sentences:
            max_score = 0.0
            matched_field = None
            matched_text = None
            
            # 在指定字段中搜索
            for field in search_fields:
                if field in sentence and sentence[field]:
                    field_text = str(sentence[field]).lower()
                    
                    # 使用SequenceMatcher计算相似度
                    score = self._calculate_similarity(keyword, field_text)
                    
                    # 也考虑关键词出现在文本中的情况
                    if keyword in field_text:
                        # 提高精确匹配的分数
                        score = max(score, 0.8 + (0.2 * len(keyword) / len(field_text)))
                    
                    if score > max_score:
                        max_score = score
                        matched_field = field
                        matched_text = field_text
            
            # 如果找到匹配且分数超过阈值
            if max_score >= threshold:
                result = sentence.copy()
                result['score'] = max_score
                result['matched_field'] = matched_field
                results.append(result)
        
        # 按分数降序排序
        results.sort(key=lambda x: x['score'], reverse=True)
        
        return results
    
    def search_by_language(self, keyword: str, sentences: List[Dict],
                          lang1: Optional[str] = None,
                          lang2: Optional[str] = None,
                          search_type: str = 'simple',
                          threshold: float = 0.1) -> List[Dict]:
        """
        按语言筛选搜索
        
        Args:
            keyword: 搜索关键词
            sentences: 句子对列表
            lang1: 第一种语言代码筛选
            lang2: 第二种语言代码筛选
            search_type: 搜索类型，'simple' 或 'advanced'
            threshold: 相似度阈值
            
        Returns:
            匹配的句子对列表
        """
        # 语言筛选
        filtered_sentences = []
        
        for sentence in sentences:
            # 检查语言条件
            if lang1 and sentence.get('lang1') != lang1:
                continue
            if lang2 and sentence.get('lang2') != lang2:
                continue
            filtered_sentences.append(sentence)
        
        # 根据搜索类型执行搜索
        if search_type == 'advanced':
            return self.advanced_search(keyword, filtered_sentences, threshold=threshold)
        else:
            return self.simple_search(keyword, filtered_sentences, threshold=threshold)
    
    def _calculate_match_score(self, keyword: str, text: str) -> float:
        """
        计算关键词匹配分数
        
        Args:
            keyword: 关键词
            text: 文本内容
            
        Returns:
            匹配分数 (0.0 - 1.0)
        """
        # 基础分数：关键词长度占文本长度的比例
        base_score = min(0.5, len(keyword) / len(text)) if text else 0
        
        # 出现次数加分
        count = text.count(keyword)
        count_score = min(0.3, count * 0.1)  # 最多加0.3分
        
        # 位置加分（关键词出现在开头权重更高）
        position = text.find(keyword)
        position_score = 0.2 if position == 0 else (0.1 if position < len(text) * 0.3 else 0)
        
        return base_score + count_score + position_score
    
    def _calculate_similarity(self, keyword: str, text: str) -> float:
        """
        计算文本相似度
        
        Args:
            keyword: 关键词
            text: 文本内容
            
        Returns:
            相似度分数 (0.0 - 1.0)
        """
        if not keyword or not text:
            return 0.0
        
        # 如果文本比关键词短，交换两者
        if len(text) < len(keyword):
            keyword, text = text, keyword
        
        # 计算最佳匹配的子串相似度
        best_score = 0.0
        for i in range(len(text) - len(keyword) + 1):
            substring = text[i:i + len(keyword)]
            score = SequenceMatcher(None, keyword, substring).ratio()
            if score > best_score:
                best_score = score
        
        return best_score


def format_search_results(results: List[Dict]) -> List[Dict]:
    """
    格式化搜索结果
    
    Args:
        results: 原始搜索结果
        
    Returns:
        格式化后的结果
    """
    formatted = []
    
    # 语言映射表
    language_names = {
        'zh': '中文',
        'vi': '越南语',
        'th': '泰语',
        'ms': '马来语',
        'id': '印尼语',
        'tl': '塔加洛语',
        'km': '高棉语',
        'lo': '老挝语',
        'my': '缅甸语',
        'si': '僧伽罗语'
    }

    for result in results:
        formatted_item = {
            'id': result.get('id'),
            'lang1': result.get('lang1'),
            'text1': result.get('text1'),
            'lang2': result.get('lang2'),
            'text2': result.get('text2'),
            'similarity': result.get('score', 0),
            'source': result.get('source', 'unknown'),
            'created_at': result.get('created_at'),
            # 添加语言显示名称
            'lang1_display': language_names.get(result.get('lang1'), result.get('lang1', '')),
            'lang2_display': language_names.get(result.get('lang2'), result.get('lang2', ''))
        }
        formatted.append(formatted_item)
    
    return formatted


def paginate_results(results: List[Dict], page: int = 1, per_page: int = 10) -> Dict:
    """
    分页处理结果
    
    Args:
        results: 结果列表
        page: 页码
        per_page: 每页数量
        
    Returns:
        分页后的结果字典
    """
    # 验证参数
    page = max(1, page)
    per_page = max(1, per_page)
    
    # 计算总数和页数
    total = len(results)
    total_pages = (total + per_page - 1) // per_page
    page = min(page, total_pages) if total_pages > 0 else 1
    
    # 计算切片范围
    start = (page - 1) * per_page
    end = start + per_page
    
    # 返回分页结果
    return {
        'results': results[start:end],
        'total': total,
        'page': page,
        'per_page': per_page,
        'total_pages': total_pages
    }